package org.biubiu0002.baiblog.core.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: biubiu0002
 * @Date: 2022-05-22 17:26
 **/
@EnableRabbit
@Configuration
@Slf4j
public class RabbitMqConfig {

    @Autowired
    private ConnectionFactory connectionFactory;

    /**
     * 更新用户信息 topic 交换机
     */
    public static final String UPDATE_USER_STATUS_EXCHANGE = "updateUserStatus.topic";
    /**
     * 更新用户信息 key 路由键
     */
    public static final String UPDATE_USER_STATUS_ROUTING_KEY = "#";
    /**
     * 更新用户信息 queue 队列
     */
    public static final String UPDATE_USER_STATUS_QUEUE = "updateUserStatus.queue";

    public static final String POST_SHARE_EXCHANGE ="postShare.topic";

    public static final String POST_SHARE_ROUTING_KEY = "#";

    public static final String POST_SHARE_QUEUE = "postShare.queue";

    public static final String UPDATE_SHARE_EXCHANGE ="updateShare.topic";

    public static final String UPDATE_SHARE_ROUTING_KEY = "#";

    public static final String UPDATE_SHARE_QUEUE = "updateShare.queue";

    public static final String FOLLOW_EXCHANGE = "follow.topic";

    public static final String FOLLOW_ROUTING_KEY = "#";

    public static final String FOLLOW_QUEUE = "follow.queue";




    /**
     * 死信队列
     */
    public static final String DLX_QUEUE = "dlx.queue";
    /**
     * 死信交换机
     */
    public static final String DLX_EXCHANGE = "dlx.exchange";
    /**
     * 死信路由键
     */
    public static final String DLX_ROUTING_KEY = "dlx.key";

    /**
     * 死信交换机参数
     */
    public static final String PARAM_DLX_X = "x-dead-letter-exchange";

    /**
     * 死信路由键参数
     */
    public static final String PARAM_DLX_KEY = "x-dead-letter-routing-key";

    @Bean("updateUserStatusExchange")
    public Exchange updateUserStatusExchange(){
        return ExchangeBuilder.topicExchange(UPDATE_USER_STATUS_EXCHANGE).build();
    }

    @Bean("updateUserStatusQueue")
    public Queue updateUserStatusQueue(){
        Map<String,Object> params = new HashMap<>(2);
        params.put(PARAM_DLX_X,DLX_EXCHANGE);
        params.put(PARAM_DLX_KEY,DLX_ROUTING_KEY);
        return new Queue(UPDATE_USER_STATUS_QUEUE, true, false, false, params);
    }

    @Bean
    public Binding updateUserStatusBinding(@Qualifier("updateUserStatusExchange")Exchange exchange,
                                           @Qualifier("updateUserStatusQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with(UPDATE_USER_STATUS_ROUTING_KEY).noargs();
    }

    @Bean("postShareExchange")
    public Exchange postShareExchange(){
        return ExchangeBuilder.topicExchange(POST_SHARE_EXCHANGE).build();
    }

    @Bean("postShareQueue")
    public Queue postShareQueue(){
        Map<String,Object> params = new HashMap<>(2);
        params.put(PARAM_DLX_X,DLX_EXCHANGE);
        params.put(PARAM_DLX_KEY,DLX_ROUTING_KEY);
        return new Queue(POST_SHARE_QUEUE, true, false, false, params);
    }

    @Bean
    public Binding postShareBinding(@Qualifier("postShareExchange")Exchange exchange,
                                           @Qualifier("postShareQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with(POST_SHARE_ROUTING_KEY).noargs();
    }

    @Bean("updateShareExchange")
    public Exchange updateShareExchange(){
        return ExchangeBuilder.topicExchange(UPDATE_SHARE_EXCHANGE).build();
    }

    @Bean("updateShareQueue")
    public Queue updateShareQueue(){
        Map<String,Object> params = new HashMap<>(2);
        params.put(PARAM_DLX_X,DLX_EXCHANGE);
        params.put(PARAM_DLX_KEY,DLX_ROUTING_KEY);
        return new Queue(UPDATE_SHARE_QUEUE, true, false, false, params);
    }

    @Bean
    public Binding updateShareBinding(@Qualifier("updateShareExchange")Exchange exchange,
                                    @Qualifier("updateShareQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with(UPDATE_SHARE_ROUTING_KEY).noargs();
    }

    @Bean("followExchange")
    public Exchange followExchange(){
        return new TopicExchange(FOLLOW_EXCHANGE,true,false);
    }

    @Bean("followQueue")
    public Queue followQueue(){
        Map<String,Object> params = new HashMap<>(2);
        params.put(PARAM_DLX_X,DLX_EXCHANGE);
        params.put(PARAM_DLX_KEY,DLX_ROUTING_KEY);
        return new Queue(FOLLOW_QUEUE,true,false,false,params);
    }

    @Bean
    public Binding followBinding(@Qualifier("followExchange") Exchange exchange,
                                 @Qualifier("followQueue") Queue queue ){
        return BindingBuilder.bind(queue).to(exchange).with(FOLLOW_ROUTING_KEY).noargs();
    }

    /**
     * 死信队列
     */
    @Bean("dlxQueue")
    public Queue dlxQueue(){
        return new Queue(DLX_QUEUE,true);
    }

    @Bean("dlxExchange")
    public DirectExchange dlxExchange(){
        return new DirectExchange(DLX_EXCHANGE,true,false);
    }

    @Bean
    public Binding bindingError(@Qualifier("dlxExchange") DirectExchange dlxExchange,
                                @Qualifier("dlxQueue") Queue dlxQueue){
        return BindingBuilder.bind(dlxQueue).to(dlxExchange).with(DLX_ROUTING_KEY);
    }

    @Bean
    public Queue testQueue(){
        Map<String,Object> params = new HashMap<>(2);
        params.put(PARAM_DLX_X,DLX_EXCHANGE);
        params.put(PARAM_DLX_KEY,DLX_ROUTING_KEY);
        return new Queue("test.queue", true, false, false, params);
    }

    @Bean
    public DirectExchange testExchange(){
        return new DirectExchange("test.exchange",true,false);
    }

    @Bean
    public Binding testBinding(@Qualifier("testExchange")DirectExchange testExchange,
                               @Qualifier("testQueue") Queue queue){
        return BindingBuilder.bind(queue).to(testExchange).with("#");
    }

//    /**
//     * 消息失败机制 - Republish 投递到死信队列
//     */
//    @Bean
//    public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate){
//        return new RepublishMessageRecoverer(rabbitTemplate,DLX_EXCHANGE,DLX_ROUTING_KEY);
//    }

    @Bean
    public RabbitTemplate rabbitTemplate(){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        //生产者-> MQ Broker 确认机制
        rabbitTemplate.setConfirmCallback((correlationData, ack, s) -> {
            log.info("[correlationData]:{} [ack]:{} [cause]:{}", correlationData,ack,s);
            if (!ack) {
                log.info("[发送失败] correlationData:{} cause:{}", correlationData ,s);
            }
        });
        //设置mandatory标志说明开启了消息故障检测模式
        rabbitTemplate.setMandatory(true);
        //MQ Broker ->消费者队列 退回机制
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) ->{
            log.warn("[消息发送失败] replyCode:{} message:{} ",replyCode,message);
        });
        return rabbitTemplate;
    }




}
